package xj.graph2d.app.prop;

import static xj.app.BaseApplicationFrame.getResourceString;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.text.EditorKit;
import javax.swing.border.BevelBorder;

import xj.graph2d.app.resources.Style;
import xj.model.uml.BasicModelElement;
import xj.model.uml.Comment;
import xj.model.uml.NamedElement;

import jsyntaxpane.DefaultSyntaxKit;

public class CommentField extends ModelPropertyField {

  public CommentField() {
  }

  public CommentField(Frame owner) { 
    super("comment", getResourceString("Comments.text"));
    JButton editButton = makeEditButton(getResourceString("Comments.edit.text"));
    editButton.setToolTipText(getResourceString("Comments.edit.tip"));

    commentDialog = new CommentDialog(owner, getResourceString("Comments.dialog.title"), 
				      this);
    editButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	updateEditorValue();
	commentDialog.showDialog();
      }
    });
    setEditor(editButton);
  }

  public void setDialogSize(int w, int h) {
    if (commentDialog != null) {
      commentDialog.setSize(w, h);
    }
  }

  @Override
  protected void updateTips() {
    if (editor != null) {
      String ctext = null;
      if (model instanceof BasicModelElement) {
	BasicModelElement m = (BasicModelElement) model;
	Comment c = m.getComment();
	if (c != null) {
	  ctext = c.getText();
	  if (ctext != null) {
	    String ctype = c.getType();
	    if (!("HTML".equals(ctype))) {
	      ctext = ctext.replaceAll("\n", "<br>");
	    }
	  }
	}
      }
      String prefix = "<html><body bgcolor='white'><b>Comment</b><br>";
      String suffix = "</body></html>";
      if (ctext == null) {
	ctext = "&nbsp;&nbsp;<i>none</i>";
      } 
      editor.setToolTipText(prefix + ctext + suffix);
    }
  }

  @Override
  public void updateEditorValue() {
    if (model instanceof BasicModelElement) {
      BasicModelElement m = (BasicModelElement) model;
      Comment c = m.getComment();
      if (c != null) {
	commentPanel.setCommentType(c.getType());
	commentPanel.setCommentText(c.getText());
      } else {
	commentPanel.setCommentType(null);
	commentPanel.setCommentText(null);
      }
    }

    if (commentDialog != null) {
      String name = null;
      String element = null;
      if (model instanceof NamedElement) {
	name = ((NamedElement) model).getName();
      }
      if (name == null || name.length() == 0) {
	name = "<unnamed>";
      }
      element = "[" + model.getElementName() + "]";

      commentDialog.setTopTitle("Comments of", name, element);
    }
  }

  @Override
  public void updateModelValue() {
    if (model instanceof BasicModelElement) {
      BasicModelElement m = (BasicModelElement) model;
      String text = commentPanel.getCommentText();
      boolean isnull = true;
      if (text != null) {
	text = text.trim();
	if (text.length() > 0) {
	  isnull = false;
	  m.setComment(commentPanel.getCommentType(), text);
	}
      }
      if (isnull) {
	// remove all comments
	Comment c = m.getComment();
	while (c != null) {
	  m.removeComment(c);
	  c = m.getComment();
	}
      }

      updateTips();
    }
  }

  protected CommentDialog commentDialog;

  protected CommentPanel commentPanel;

}

class CommentDialog extends JDialog implements ActionListener {

  public CommentDialog(Frame owner, String title, CommentField field) {
    super(owner, title, true);
    setAlwaysOnTop(true);

    this.field = field;

    JPanel topPanel = new JPanel();
    topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 5, 10));
    topPanel.setLayout(new BorderLayout());
    add(topPanel);

    commentPanel = new CommentPanel(field);
    topPanel.add(commentPanel, BorderLayout.CENTER);

    titleLabel = new TitleComponent();
    titleLabel.setNameStyle(Font.ITALIC);
    titleLabel.setNameColor(new Color(0, 0, 128));
    titleLabel.setElementColor(new Color(0, 128, 0));
    topPanel.add(titleLabel, BorderLayout.NORTH);

    JPanel buttonPanel = new JPanel();
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
    buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
    cancelButton = new JButton("Cancel");
    cancelButton.addActionListener(this);
    buttonPanel.add(cancelButton);
    okButton = new JButton("Ok");
    okButton.addActionListener(this);
    buttonPanel.add(okButton);
    topPanel.add(buttonPanel, BorderLayout.SOUTH);

    setSize(800, 500);
  }

  public void showDialog() {
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    Dimension dialogSize = getSize();
    setLocation(screenSize.width / 2 - dialogSize.width / 2, 
		screenSize.height / 2 - dialogSize.height / 2);
    setVisible(true);
  }

  public void setTopTitle(String prefix, String name, String element) {
    if (commentPanel != null &&
	titleLabel != null) { 
      commentPanel.setBorder(BorderFactory.createEtchedBorder());
      titleLabel.setTitle(prefix, name, element);
    }
  }

  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source == okButton) {
      if (field != null) {
	field.updateModelValue();
	field.updateShape();
      }
      setVisible(false);
    } else {
      // cancel
      setVisible(false);
    }
  }

  protected CommentField field;

  protected CommentPanel commentPanel;

  protected JButton okButton, cancelButton;

  protected TitleComponent titleLabel;

}

class CommentPanel extends JPanel {

  CommentPanel(CommentField field) {
    this(field, true);
  }

  CommentPanel(CommentField field, boolean hasToolbar) {
    if (field != null) {
      field.commentPanel = this;
    }

    setLayout(new BorderLayout());

    DefaultSyntaxKit.initKit();
    body = new JEditorPane();
    JScrollPane scrollPane = new JScrollPane(body);
    body.setFont(Style.font);
    body.setContentType("text/plain");
    body.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));

    if (hasToolbar) { 
      toolbar = new JToolBar();
      toolbar.setRollover(true);
      toolbar.setFocusable(false);
      toolbar.setFloatable(false);

      EditorKit kit = body.getEditorKit();
      if (kit instanceof DefaultSyntaxKit) {
	DefaultSyntaxKit defaultSyntaxKit = (DefaultSyntaxKit) kit;
	defaultSyntaxKit.addToolBarActions(body, toolbar);
      }
      toolbar.validate();
    }

    type = new JComboBox();
    type.addItem("text");
    type.addItem("HTML");
    type.setEditable(true);
    type.setBackground(Color.white);
    type.setFont(Style.editorFont);

    type.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
	if (e.getStateChange() == ItemEvent.SELECTED) {
	  String text = body.getText();
	  String langType = type.getSelectedItem().toString();
	  if (langType != null) { 
	    langType = langType.toLowerCase(); 
	  }
	  String contentType = "text/plain";
	  if ("html".equals(langType)) { 
	    contentType = "text/xhtml";
	  }
	  body.setContentType(contentType); 
	  body.setText(text);
	  if (toolbar != null) { 
	    toolbar.removeAll();
	    EditorKit kit = body.getEditorKit();
	    if (kit instanceof DefaultSyntaxKit) {
	      DefaultSyntaxKit defaultSyntaxKit = (DefaultSyntaxKit) kit;
	      defaultSyntaxKit.addToolBarActions(body, toolbar);
	    }
	    toolbar.validate();
	  }
	  body.requestFocusInWindow();
	}
      }
    });

    JPanel topPanel = new JPanel();
    topPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    topPanel.add(new JLabel("Content type"));
    topPanel.add(type);
    if (toolbar != null) { 
      topPanel.add(toolbar);
    }

    add(topPanel, BorderLayout.NORTH);
    add(scrollPane, BorderLayout.CENTER);
  }

  String getCommentType() {
    if (type != null) {
      // return type.getText();
      return (String) type.getSelectedItem();
    }
    return null;
  }

  void setCommentType(String s) {
    if (type != null) {
      // type.setText(s);
      if (s != null) {
	type.setSelectedItem(s);
      }
    }
  }

  String getCommentText() {
    if (body != null) {
      return body.getText();
    }
    return null;
  }

  void setCommentText(String s) {
    if (body != null) {
      body.setText(s);
    }
  }

  protected JEditorPane body;

  protected JComboBox type;

  protected JTextField name;

  protected JToolBar toolbar; 

}
